package com.alvin.abp.web.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.alvin.abp.common.constant.Constants;
import com.alvin.abp.common.context.CurrentUserContext;
import com.alvin.abp.domain.AlvinUser;
import com.alvin.abp.domain.Bonus;
import com.alvin.abp.domain.Point;
import com.alvin.abp.domain.Record;
import com.alvin.abp.domain.Rule;
import com.alvin.abp.domain.Status;
import com.alvin.abp.domain.editor.EntityPropertyEditor;
import com.alvin.abp.domain.validator.BonusValidator;
import com.alvin.abp.service.BonusService;
import com.alvin.abp.service.UserService;

@Controller
public class RecordController {
	@Autowired
	private UserService userService;
	@Autowired
	private BonusService bonusService;
	@Autowired
	private BonusValidator bonusValidator;
	
	protected final Log logger = LogFactory.getLog(getClass());
	
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.registerCustomEditor(AlvinUser.class, new EntityPropertyEditor(AlvinUser.class));
		binder.registerCustomEditor(Rule.class, new EntityPropertyEditor(Rule.class));
	}
	
	@RequestMapping(value = "/service/info.htm", method = RequestMethod.GET)	
	public void retreiveInfo(@RequestParam("mobile") String mobile, HttpServletResponse response) {
		try {

			AlvinUser user = userService.loadUserBasicInfo(mobile);
			Map<String, String> result = new HashMap<String, String>();
			if(user != null){
				result.put("exist", "1");
				result.put("balance", user.getBalance().toString());
				result.put("mobile", user.getMobile());
			}else{
				result.put("exist", "0");
			}
			response.setContentType("text/html");
			response.setCharacterEncoding("utf-8");
			response.getWriter().print(jsonStr(result));

		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	@RequestMapping(value = "/service/retreive.htm", method = RequestMethod.GET)	
	public void retreive(@RequestParam("code") String code, HttpServletResponse response) {
		try {

			Point point = bonusService.readPoint(code);
			Map<String, String> result = new HashMap<String, String>();
			result.put("point", Integer.toString(point.getPoint()));
			result.put("status", point.getQrStatus().getValue());
			response.setContentType("text/html");
			response.setCharacterEncoding("utf-8");
			response.getWriter().print(jsonStr(result));

		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	@RequestMapping(value = "/service/register.htm", method = RequestMethod.POST)	
	public void register(@RequestParam("mobile") String mobile, @RequestParam("code") String code, HttpServletResponse response) {
		try{
			Map<String, String> result = new HashMap<String, String>();
			response.setContentType("text/html");
			response.setCharacterEncoding("utf-8");
			
			AlvinUser user = userService.loadUserBasicInfo(mobile);
			if(user == null) {
				int point = 0;
				Point pointObj = bonusService.readPoint(code);
				if(pointObj != null){
					if(pointObj.getQrStatus() == Status.QR_HAD_INTEGRAL){
						result.put("status", Constants.FAILURE);
						result.put("error", Constants.EXIST);
					}
					point = pointObj.getPoint();
				}
				
				userService.register(mobile, point);
				result.put("status", Constants.SUCCESS);
			}else{
				result.put("status", Constants.FAILURE);
				result.put("error", Constants.EXIST);
			}
			
			response.getWriter().print(jsonStr(result));
		}catch(IOException ex){
			ex.printStackTrace();
		}
		
	}
	
	@RequestMapping(value = "/service/update.htm", method = RequestMethod.POST)	
	public void update(@RequestParam("mobile") String mobile, @RequestParam("code") String code, HttpServletResponse response) {
		try{
			Map<String, String> result = new HashMap<String, String>();
			response.setContentType("text/html");
			response.setCharacterEncoding("utf-8");
			
			Bonus bonus = new Bonus();
			AlvinUser user = userService.loadUserBasicInfo(mobile);
			
			if(user != null && code != null){
				bonus.setUser(user);
				bonus.setCode(code);
			}else{
				result.put("status", Constants.FAILURE);
				result.put("error", Constants.NONEXIST);
			}
			
			int point = 0;
			Point pointObj = bonusService.readPoint(bonus.getCode());
			if(pointObj != null){
				if(pointObj.getQrStatus() == Status.QR_HAD_INTEGRAL){
					result.put("status", Constants.FAILURE);
					result.put("error", Constants.EXIST);
				}
				point = pointObj.getPoint();
				
				BigDecimal base = user.getBalance();
				BigDecimal balance = base.add(new BigDecimal(point));
				user.setBalance(balance);
				userService.updateBalance(user);
				result.put("status", Constants.SUCCESS);
			}else{
				result.put("status", Constants.FAILURE);
				result.put("error", Constants.EMPTY);
			}
			
			response.getWriter().print(jsonStr(result));
		}catch(IOException ex){
			ex.printStackTrace();
		}
	}
	
	@RequestMapping(value = "/records.htm", method = RequestMethod.GET)
	public String recordsForm(@RequestParam("id") Long id, ModelMap model) {
		AlvinUser user = userService.readUserById(id);
		List<Record> records = userService.readRecords(id);
		user.setRecords(records);
		model.addAttribute("user", user);
		return "user/records";
	}
	
	@RequestMapping(value="/collect.htm", method = RequestMethod.GET)
	public String collectForm(@RequestParam(value="status", required=false) String status, ModelMap model){
		AlvinUser user = userService.readUserById(CurrentUserContext.getCurrentUser().getId());
		Bonus bonus = new Bonus();
		model.addAttribute(bonus);
		model.addAttribute("status", status);
		model.addAttribute("user", user);
		return "home";
	}
	
	@RequestMapping(value="/collect.htm", method = RequestMethod.POST)
	public String collectPoint(@ModelAttribute("bonus") Bonus bonus, Errors errors, ModelMap model) {
		ValidationUtils.invokeValidator(bonusValidator, bonus, errors);
		
		model.addAttribute(bonus);
		AlvinUser user = userService.readUserById(CurrentUserContext.getCurrentUser().getId());
		model.addAttribute("user", user);
		
		if(errors.hasErrors()) {
			model.addAllAttributes(errors.getAllErrors());
			return "home";
		}else{
			bonusService.addBonus(bonus);
			return "redirect:/collect.htm?status=success";
		}
	}
	
	private String jsonStr(Map<String, ? extends Object> map) {

		StringBuffer jsonStr = new StringBuffer("{");
		Set<String> keys = map.keySet();

		for (String key : keys) {
			jsonStr.append("\"").append(key).append("\":\"").append(map.get(key)).append("\",");
		}

		jsonStr.deleteCharAt(jsonStr.length()-1);
		jsonStr.append("}");

		return jsonStr.toString();
	}
}
